import CryptoJS from "crypto-js"
import uploadConfig from "@/config/upload"
import CityLinkageJson from "@/components/ma-cityLinkage/lib/city.json"
import isServer from "./isServer"
// eslint-disable-next-line vue/prefer-import-from-vue
import { isObject, isArray } from "@vue/shared"
const typeColor = (type = "default") => {
  let color = ""
  switch (type) {
    case "default":
      color = "#35495E"
      break
    case "primary":
      color = "#3488ff"
      break
    case "success":
      color = "#43B883"
      break
    case "warning":
      color = "#e6a23c"
      break
    case "danger":
      color = "#f56c6c"
      break
    default:
      break
  }
  return color
}

const tool = {}

/**
 * LocalStorage
 */
tool.local = {
  set(table, settings) {
    const _set = JSON.stringify(settings)
    return localStorage.setItem(table, _set)
  },
  get(table) {
    let data = localStorage.getItem(table)
    try {
      data = JSON.parse(data)
    } catch (err) {
      return null
    }
    return data
  },
  remove(table) {
    return localStorage.removeItem(table)
  },
  clear() {
    return localStorage.clear()
  }
}

/**
 * SessionStorage
 */
tool.session = {
  set(table, settings) {
    const _set = JSON.stringify(settings)
    return sessionStorage.setItem(table, _set)
  },
  get(table) {
    let data = sessionStorage.getItem(table)
    try {
      data = JSON.parse(data)
    } catch (err) {
      return null
    }
    return data
  },
  remove(table) {
    return sessionStorage.removeItem(table)
  },
  clear() {
    return sessionStorage.clear()
  }
}

/**
 * CookieStorage
 */
tool.cookie = {
  set(name, value, config = {}) {
    const cfg = {
      expires: null,
      path: null,
      domain: null,
      secure: false,
      httpOnly: false,
      ...config
    }
    let cookieStr = `${name}=${escape(value)}`
    if (cfg.expires) {
      const exp = new Date()
      exp.setTime(exp.getTime() + parseInt(cfg.expires) * 1000)
      cookieStr += `;expires=${exp.toGMTString()}`
    }
    if (cfg.path) {
      cookieStr += `;path=${cfg.path}`
    }
    if (cfg.domain) {
      cookieStr += `;domain=${cfg.domain}`
    }
    document.cookie = cookieStr
  },
  get(name) {
    const arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"))
    if (arr != null) {
      return unescape(arr[2])
    } else {
      return null
    }
  },
  remove(name) {
    const exp = new Date()
    exp.setTime(exp.getTime() - 1)
    document.cookie = `${name}=;expires=${exp.toGMTString()}`
  }
}

/* Fullscreen */
tool.screen = (element) => {
  const isFull = !!(
    document.webkitIsFullScreen ||
    document.mozFullScreen ||
    document.msFullscreenElement ||
    document.fullscreenElement
  )
  if (isFull) {
    if (document.exitFullscreen) {
      document.exitFullscreen()
    } else if (document.msExitFullscreen) {
      document.msExitFullscreen()
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen()
    } else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen()
    }
  } else {
    if (element.requestFullscreen) {
      element.requestFullscreen()
    } else if (element.msRequestFullscreen) {
      element.msRequestFullscreen()
    } else if (element.mozRequestFullScreen) {
      element.mozRequestFullScreen()
    } else if (element.webkitRequestFullscreen) {
      element.webkitRequestFullscreen()
    }
  }
}

// 城市代码翻译成名称
tool.cityToCode = function (province, city = undefined, area = undefined, split = " / ") {
  try {
    const provinceData = CityLinkageJson.filter((item) => province == item.code)[0]
    if (!city) {
      return provinceData.name
    }
    const cityData = provinceData.children.filter((item) => city == item.code)[0]

    if (!area) {
      return [provinceData.name, cityData.name].join(split)
    }
    const areaData = cityData.children.filter((item) => area == item.code)[0]

    return [provinceData.name, cityData.name, areaData.name].join(split)
  } catch (e) {
    return ""
  }
}

/* 复制对象 */
tool.objCopy = (obj) => {
  if (obj === undefined) {
    return undefined
  }
  return JSON.parse(JSON.stringify(obj))
}

tool.generateId = function () {
  return Math.floor(Math.random() * 100000 + Math.random() * 20000 + Math.random() * 5000)
}

tool.viewImage = function (path, defaultStorage = "LOCAL") {
  if (path.indexOf("http") !== -1) {
    return path
  }
  const mode = tool.local.get("site_storage_mode") ? tool.local.get("site_storage_mode").toUpperCase() : defaultStorage
  return uploadConfig.storage[mode] + path
}

tool.showFile = function (hash, defaultStorage = "LOCAL") {
  if (hash.indexOf(".") !== -1) {
    return tool.viewImage(hash, defaultStorage)
  }
  const baseURL =
    import.meta.env.VITE_APP_OPEN_PROXY === "true"
      ? import.meta.env.VITE_APP_PROXY_PREFIX
      : import.meta.env.VITE_APP_BASE_URL
  if (typeof hash === "object") {
    return hash.map((item) => {
      item = baseURL + "/core/system/downloadByHash/" + item
      return item
    })
  } else {
    return baseURL + "/core/system/downloadByHash/" + hash
  }
}

/* 日期格式化 */
tool.dateFormat = (date, fmt = "yyyy-MM-dd hh:mm:ss", isDefault = "-") => {
  if (date.toString().length == 10) {
    date = date * 1000
  }
  date = new Date(date)

  if (date.valueOf() < 1) {
    return isDefault
  }
  const o = {
    "M+": date.getMonth() + 1, //月份
    "d+": date.getDate(), //日
    "h+": date.getHours(), //小时
    "m+": date.getMinutes(), //分
    "s+": date.getSeconds(), //秒
    "q+": Math.floor((date.getMonth() + 3) / 3), //季度
    S: date.getMilliseconds() //毫秒
  }
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length))
  }
  for (const k in o) {
    if (new RegExp("(" + k + ")").test(fmt)) {
      fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length))
    }
  }
  return fmt
}

/* 千分符 */
tool.groupSeparator = (num) => {
  num = num + ""
  if (!num.includes(".")) {
    num += "."
  }
  return num
    .replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) {
      return $1 + ","
    })
    .replace(/\.$/, "")
}

tool.md5 = (str) => {
  return CryptoJS.MD5(str).toString()
}

tool.base64 = {
  encode(data) {
    return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data))
  },
  decode(cipher) {
    return CryptoJS.enc.Base64.parse(cipher).toString(CryptoJS.enc.Utf8)
  }
}

tool.aes = {
  encode(data, secretKey) {
    const result = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(secretKey), {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })
    return result.toString()
  },
  decode(cipher, secretKey) {
    const result = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(secretKey), {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })
    return CryptoJS.enc.Utf8.stringify(result)
  }
}

tool.capsule = (title, info, type = "primary") => {
  console.log(
    `%c ${title} %c ${info} %c`,
    "background:#35495E; padding: 1px; border-radius: 3px 0 0 3px; color: #fff;",
    `background:${typeColor(type)}; padding: 1px; border-radius: 0 3px 3px 0;  color: #fff;`,
    "background:transparent"
  )
}

tool.formatSize = (size) => {
  if (typeof size == "undefined") {
    return "0"
  }
  const units = ["B", "KB", "MB", "GB", "TB", "PB"]
  let index = 0
  for (let i = 0; size >= 1024 && i < 5; i++) {
    size /= 1024
    index = i
  }
  return Math.round(size, 2) + units[index]
}

tool.download = (res, downName = "") => {
  const aLink = document.createElement("a")
  let fileName = downName
  let blob = res //第三方请求返回blob对象

  //通过后端接口返回
  if (res.headers && res.data) {
    blob = new Blob([res.data], {
      type: res.headers["content-type"].replace(";charset=utf8", "")
    })
    if (!downName) {
      const contentDisposition = decodeURI(res.headers["content-disposition"])
      const result = contentDisposition.match(/filename=\"(.+)/gi)
      fileName = result[0].replace(/filename=\"/gi, "")
      fileName = fileName.replace('"', "")
    }
  }

  aLink.href = URL.createObjectURL(blob)
  // 设置下载文件名称
  aLink.setAttribute("download", fileName)
  document.body.appendChild(aLink)
  aLink.click()
  document.body.removeChild(aLink)
  URL.revokeObjectURL(aLink.href)
}

/**
 * 对象转url参数
 * @param {*} data
 * @param {*} isPrefix
 */
tool.httpBuild = (data, isPrefix = false) => {
  const prefix = isPrefix ? "?" : ""
  const _result = []
  for (const key in data) {
    const value = data[key]
    // 去掉为空的参数
    if (["", undefined, null].includes(value)) {
      continue
    }
    if (value.constructor === Array) {
      value.forEach((_value) => {
        _result.push(encodeURIComponent(key) + "[]=" + encodeURIComponent(_value))
      })
    } else {
      _result.push(encodeURIComponent(key) + "=" + encodeURIComponent(value))
    }
  }

  return _result.length ? prefix + _result.join("&") : ""
}

tool.getRequestParams = (url) => {
  const theRequest = new Object()
  if (url.indexOf("?") != -1) {
    const params = url.split("?")[1].split("&")
    for (let i = 0; i < params.length; i++) {
      const param = params[i].split("=")
      theRequest[param[0]] = decodeURIComponent(param[1])
    }
  }
  return theRequest
}

tool.attachUrl = (path, defaultStorage = "LOCAL") => {
  return uploadConfig.storage[defaultStorage] + path
}

/**
 * 获取token
 */
tool.getToken = () => {
  return tool.local.get("token")
}
/**
 * 转Unix时间戳
 */

tool.toUnixTime = (date) => {
  return Math.floor(new Date(date).getTime() / 1000)
}

tool.arrSum = (arr) => {
  let sum = 0
  arr.map((item) => (sum += item))
  return sum
}
/* istanbul ignore next */
const resizeHandler = function (entries) {
  for (const entry of entries) {
    const listeners = entry.target.__resizeListeners__ || []
    if (listeners.length) {
      listeners.forEach((fn) => {
        fn()
      })
    }
  }
}
/* istanbul ignore next */
tool.addResizeListener = function (element, fn) {
  if (isServer || !element) return
  if (!element.__resizeListeners__) {
    element.__resizeListeners__ = []
    element.__ro__ = new ResizeObserver(resizeHandler)
    element.__ro__.observe(element)
  }
  element.__resizeListeners__.push(fn)
}

/* istanbul ignore next */
tool.removeResizeListener = function (element, fn) {
  if (!element || !element.__resizeListeners__) return
  element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1)
  if (!element.__resizeListeners__.length) {
    element.__ro__.disconnect()
  }
}

tool.isEmpty = (val) => {
  return (!val && val !== 0) || (isArray(val) && !val.length) || (isObject(val) && !Object.keys(val).length)
}

tool.typeOf = (obj) => {
  const toString = Object.prototype.toString
  const map = {
    "[object Boolean]": "boolean",
    "[object Number]": "number",
    "[object String]": "string",
    "[object Function]": "function",
    "[object Array]": "array",
    "[object Date]": "date",
    "[object RegExp]": "regExp",
    "[object Undefined]": "undefined",
    "[object Null]": "null",
    "[object Object]": "object"
  }
  return map[toString.call(obj)]
}

tool.deepCopy = (data) => {
  const t = tool.typeOf(data)
  let o

  if (t === "array") {
    o = []
  } else if (t === "object") {
    o = {}
  } else {
    return data
  }

  if (t === "array") {
    for (let i = 0; i < data.length; i++) {
      o.push(tool.deepCopy(data[i]))
    }
  } else if (t === "object") {
    for (const i in data) {
      o[i] = tool.deepCopy(data[i])
    }
  }
  return o
}

/**
 * @description 获取随机uuid
 * @param hasHyphen 是否有连接符
 */
tool.uuid = (hasHyphen) => {
  return g.guid(16)
}
const pretty = (title, text, type = "primary") => {
  console.log(
    `%c ${title} %c ${text} %c`,
    `background:${typeColor(type)};border:1px solid ${typeColor(
      type
    )}; padding: 1px; border-radius: 2px 0 0 2px; color: #fff;`,
    `border:1px solid ${typeColor(type)}; padding: 1px; border-radius: 0 2px 2px 0; color: ${typeColor(type)};`,
    "background:transparent"
  )
}
tool.throwError = (scope, m) => {
  pretty(scope, m, "danger")
}

/**
 * 处理拉平树结构
 * @param stateTree
 * @returns {*[]}
 */
tool.compileFlatState = (stateTree) => {
  let keyCounter = 0
  const childrenKey = "children"
  const flatTree = []

  const flattenChildren = (node, parent, parentKeys) => {
    if (tool.isEmpty(node)) return
    node.nodeKey = keyCounter++
    flatTree[node.nodeKey] = { node: node, nodeKey: node.nodeKey }
    if (typeof parent !== "undefined") {
      flatTree[node.nodeKey].parent = parent.nodeKey
      flatTree[parent.nodeKey][childrenKey].push(node.nodeKey)
    }
    const parents = parentKeys ? parentKeys.split(",").map((i) => +i) : []
    // 拼接parents
    if (typeof parentKeys !== "undefined") {
      parents.push(parent.nodeKey)
      flatTree[node.nodeKey].parents = parents
    }

    if (node[childrenKey]) {
      flatTree[node.nodeKey][childrenKey] = []
      node[childrenKey].forEach((child) => flattenChildren(child, node, parents.join(",")))
    }
  }

  flattenChildren(stateTree)

  return flatTree
}

const oldList = {}
tool.searchEvent = (keyword, list = [], keywordProp = [], name) => {
  if (!oldList[name]) {
    oldList[name] = tool.deepCopy(list)
  }
  if (!keyword) return oldList[name]
  const newList = []
  keywordProp.forEach((item) => {
    oldList[name].forEach((i) => {
      if (i[item].includes(keyword)) {
        newList.push(i)
      }
    })
  })
  return newList
}
export default tool
